﻿using System;
using CommonFramework.Log;

namespace CommonFramework.Serialize.BytesArray.Private
{
    /// <summary>
    /// 字节数组扩容机制
    /// </summary>
    internal class BytesExtender : IBytesProvider
    {
        public byte[] Bytes;
        protected int _writeIndex;
        protected int _readIndex;

        private int _initSize;

        public BytesExtender(byte[] initBytes,int offset,int count)
        {
            if (initBytes == null)
            {
                Bytes = new byte[count];
            }
            else if(offset>0 || count!=initBytes.Length)
            {
                Bytes = new byte[count];
                Buffer.BlockCopy(initBytes,offset,Bytes,0,count);
                ReadIndex = 0;
                WriteIndex = count;
            }
            else
            {
                Bytes = initBytes;
                ReadIndex = 0;
                WriteIndex = Bytes.Length;
            }
            _initSize = Bytes.Length;
        }

        public byte[] CurrentBytes() => Bytes;
        
        public byte[] WriteBytesView() => Bytes;
        public int WriteIndex 
        {
            get=>_writeIndex;
            set => _writeIndex = value;
        }

        public byte[] ReadBytesView() => Bytes;
        public int ReadIndex
        {
            get=>_readIndex;
            set=>_readIndex=value;
        }

        public int DataLength()
        {
            return  _writeIndex - _readIndex;
        }
        public int TotalLength()
        {
            return Bytes?.Length ?? 0;
        }
        public int RemainLength()
        {
            return TotalLength() - _writeIndex;
        }

        /// <summary>
        /// 扩容到指定大小
        /// </summary>
        public virtual void ExtendSizeTo(int newSize)
        {
            if (newSize < _initSize || newSize < DataLength())
                return;

            int extendToSize = DataLength();
            while (extendToSize < newSize)
                extendToSize *= 2;

            int dataLen = DataLength();
            byte[] extendBytes = new byte[extendToSize];
            Buffer.BlockCopy(this.Bytes,this.ReadIndex,extendBytes,0,dataLen);

            this.Bytes = extendBytes;
            this.ReadIndex = 0;
            this.WriteIndex = dataLen;

            if (extendToSize > 3 * BytesBuffer.PER_CHUNK_SIZE)
            {
                LogUtil.LogWarning("BytesBuffer alloc large bytes array with size="+extendToSize);
            }
        }
        /// <summary>
        /// 用户数据迁移到数组头部,增加Remain
        /// </summary>
        public virtual void MoveDataToOrigin()
        {
            if (ReadIndex == 0)
                return;

            int dataLen= this.DataLength();
            Buffer.BlockCopy(this.Bytes,ReadIndex,this.Bytes,0,this.DataLength());

            this.ReadIndex = 0;
            this.WriteIndex = dataLen;
        }

        /// <summary>
        /// 清空释放资源
        /// </summary>
        public virtual void Clear()
        {
            Bytes = null;
            WriteIndex = 0;
            ReadIndex = 0;
        }
    }
}